package com.example.service.impl;

import com.example.config.SMSProperties;
import com.example.dto.RegisterDto;
import com.example.execption.TijianException;
import com.example.execption.TijianExceptionEnum;
import com.example.dto.UserLoginDto;
import com.example.mapper.UserMapper;
import com.example.pojo.User;
import com.example.service.CodeService;
import com.example.util.SMSUtil;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.logging.Logger;
import org.mybatis.logging.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class CodeServiceImpl implements CodeService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private SMSProperties smsProperties;
//    @Autowired
//    private RedisTemplate redisTemplate;


    private static final Logger logger = LoggerFactory.getLogger(CodeServiceImpl.class);

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    /**
     * 发送短信验证码（登录时）
     * @param phone
     */
    @Override
    @Transactional
    public void getVICode(String phone) {
        String code = (int)(Math.random() * 1000000) + "";
        while (code.length() < 6) {
            code = "0" + code;
        }
        // 发送验证码
        SMSUtil.sendMessage(smsProperties.getRegionId(), smsProperties.getAccessKeyId(),
                smsProperties.getAccessKeySecret(), smsProperties.getSignName(),
                smsProperties.getTemplateCode(), phone, code);
        // 保存到redis数据库
        redisTemplate.opsForValue().set(SMSProperties.LOGIN + phone, code, 180, TimeUnit.MINUTES);
        System.out.println("Stored code in Redis: " + code);
        log.info("Stored code in Redis for phone {}: {}", phone, code); // 增加日志输出

    }

    @Override
    @Transactional
    public User login(UserLoginDto userLoginDto) {
        log.info("Received login request: {}", userLoginDto);
        User user = userMapper.selectByUserId(userLoginDto.getUserId());

        // 从前端传来的数据中获取 userId 和 VICode
        String userId = userLoginDto.getUserId();
        String VICode = userLoginDto.getVICode();

        // 这里可以对 userId 和 VICode 做进一步的验证，例如非空检查等

        // 在日志中输出获取到的 userId 和 VICode
        log.info("User ID from request: {}", userId);
        log.info("VICode from request: {}", VICode);

        // 可以进一步处理业务逻辑，例如查询用户信息等

//        // 这里示例直接返回一个虚拟的 User 对象
//        User user = new User();
//        user.setUserId(userId); // 设置用户ID
//        user.setUsername("TestUser"); // 设置用户名，这里假设是测试用例
//        redisTemplate.delete(redisKey);

        return user;
    }


    @Override
    @Transactional
    public User register(RegisterDto registerDto) {
        // Check if VICode is null
        if (registerDto.getVICode() == null) {
            throw new IllegalArgumentException("Verification code cannot be null.");
        }

        // Check if userId already exists
        User existingUser = userMapper.selectOrderByUserId(registerDto.getUserId());
        if (existingUser != null) {
            throw new TijianException(TijianExceptionEnum.USER_NOT_EXISTS);
        }

        // Validate input fields
        validateRegistrationFields(registerDto);

        // Verify the verification code
        verifyVICode(registerDto.getUserId(), registerDto.getVICode());

        // Convert frontend date string to Date type, assuming birthday format is "yyyy-MM-dd"
        Date birthday = parseDate(registerDto.getBirthday());

        // Create User object from DTO data
        User user = new User();
        user.setUserId(registerDto.getUserId());
        user.setPassword(registerDto.getPassword());
        user.setRealName(registerDto.getRealName());
        user.setSex(registerDto.getSex());
        user.setIdentityCard(registerDto.getIdentityCard());
        user.setBirthday(birthday);
        user.setUserType(registerDto.getUserType());

        // Save user to database
        userMapper.insert(user);
        return user;
    }

    private void validateRegistrationFields(RegisterDto registerDto) {
        if (registerDto.getUserId() == null || registerDto.getUserId().isEmpty()) {
            throw new IllegalArgumentException("Phone number cannot be empty.");
        }
        if (registerDto.getPassword() == null || registerDto.getPassword().isEmpty()) {
            throw new IllegalArgumentException("Password cannot be empty.");
        }
        if (registerDto.getRealName() == null || registerDto.getRealName().isEmpty()) {
            throw new IllegalArgumentException("Real name cannot be empty.");
        }
        if (registerDto.getBirthday() == null || registerDto.getBirthday().isEmpty()) {
            throw new IllegalArgumentException("Birthday cannot be empty.");
        }
        if (registerDto.getSex() == null) {
            throw new IllegalArgumentException("Gender cannot be empty.");
        }
        if (registerDto.getIdentityCard() == null || registerDto.getIdentityCard().isEmpty()) {
            throw new IllegalArgumentException("Identity card number cannot be empty.");
        }
        if (registerDto.getUserType() == null) {
            throw new IllegalArgumentException("User type cannot be empty.");
        }
    }

    private void verifyVICode(String userId, String VICode) {
        if (VICode == null || VICode.isEmpty()) {
            throw new IllegalArgumentException("Verification code cannot be null or empty.");
        }

        String redisKey = SMSProperties.LOGIN + userId;
        String storedCode = (String) redisTemplate.opsForValue().get(redisKey);

        if (storedCode == null || storedCode.isEmpty()) {
            throw new TijianException(TijianExceptionEnum.VL_CODE_EXPIRED);
        }

        // 将用户输入的验证码转换为与Redis中存储的验证码相同的格式
        String inputCode = VICode.trim().toLowerCase();
        if (!storedCode.equals(inputCode)) {
            throw new TijianException(TijianExceptionEnum.VL_CODE_ERROR);
        }

        // Optionally, delete the verification code from Redis after successful validation
        // redisTemplate.delete(redisKey);
    }
    private Date parseDate(String dateString) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return sdf.parse(dateString);
        } catch (ParseException e) {
            throw new RuntimeException("Invalid date format", e);
        }
    }
}
